package com.quad.innovators.salesease.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.quad.innovators.salesease.common.utils.SystemCodeUtils;
import com.quad.innovators.salesease.enums.ArrivalScanStatusEnum;
import com.quad.innovators.salesease.enums.BackstageStatusEnum;
import com.quad.innovators.salesease.enums.ProductActualStatusEnum;
import com.quad.innovators.salesease.enums.ResultCode;
import com.quad.innovators.salesease.enums.StatusEnum;
import com.quad.innovators.salesease.enums.SystemCodeEnum;
import com.quad.innovators.salesease.exception.BusinessException;
import com.quad.innovators.salesease.model.entity.base.Product;
import com.quad.innovators.salesease.model.entity.stock.ProductInfoIdentity;
import com.quad.innovators.salesease.model.entity.warehouse.ArrivalOrder;
import com.quad.innovators.salesease.model.excel.IdentityCodeExcel;
import com.quad.innovators.salesease.model.form.warehouse.ArrivalOrderDetailForm;
import com.quad.innovators.salesease.model.form.warehouse.ArrivalOrderForm;
import com.quad.innovators.salesease.service.base.ProductService;
import com.quad.innovators.salesease.service.stock.ProductInfoIdentityService;
import com.quad.innovators.salesease.service.warehouse.ArrivalOrderDetailService;
import com.quad.innovators.salesease.service.warehouse.ArrivalOrderService;

import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

/**
 * @author : shanshan.li
 * @createTime : 2025/3/27 16:51
 * @Version : 1.0 
 */
@Getter
@Setter
@Component
@RequiredArgsConstructor
public class IdentityCodeListener implements ReadListener<IdentityCodeExcel> {

    private String arrivalCode = "";
    private List<IdentityCodeExcel> identityCodeExcels = Lists.newArrayList();
    private final ProductService productService;
    private final ArrivalOrderDetailService arrivalOrderDetailService;
    private final ArrivalOrderService arrivalOrderService;
    private final ProductInfoIdentityService productInfoIdentityService;

    @Override
    public void invoke(IdentityCodeExcel identityCodeExcel, AnalysisContext analysisContext) {
        // 判断数据是否都不为空
        if (ObjectUtils.isNull(identityCodeExcel) || StringUtils.isBlank(identityCodeExcel.getIdentityCode()) || StringUtils.isBlank(identityCodeExcel.getProductName()) || StringUtils.isBlank(identityCodeExcel.getPackingCode())) {
            throw BusinessException.resultCode(ResultCode.EXCEL_DATA_NOT_NULL);
        }
        identityCodeExcels.add(identityCodeExcel);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        try {
            // 判断要导入的数据是否存在
            Set<String> productExcelNameSet = identityCodeExcels.stream().map(IdentityCodeExcel::getProductName).collect(Collectors.toSet());
            List<Product> productList = productService.list(new QueryWrapper<Product>().lambda().eq(Product::getStatus, StatusEnum.ENABLE.getValue()).in(Product::getName, productExcelNameSet));
            Set<String> productDataSourceSet = productList.stream().map(Product::getName).collect(Collectors.toSet());
            if (productExcelNameSet.size() > productDataSourceSet.size()) {
                throw BusinessException.resultCode(ResultCode.EXCEL_PRODUCT_NOT_FOUNT);
            }

            // 判断每个包装码是否为同一个产品
            Map<String, List<IdentityCodeExcel>> identityCodeExcelMap = identityCodeExcels.stream().collect(Collectors.groupingBy(IdentityCodeExcel::getPackingCode));
            for (Map.Entry<String, List<IdentityCodeExcel>> entry : identityCodeExcelMap.entrySet()) {
                List<IdentityCodeExcel> identityGroupPackingCodeList = entry.getValue();
                String productName = "";
                for (IdentityCodeExcel identityCodeExcel : identityGroupPackingCodeList) {
                    if (StringUtils.isBlank(productName)) {
                        productName = identityCodeExcel.getProductName();
                    }
                    if (!StringUtils.equals(productName, identityCodeExcel.getProductName())) {
                        throw BusinessException.resultCode(ResultCode.EXCEL_PRODUCT_NOT_PACKING);
                    }
                }
                productName = "";
            }

            // 判断包装码下面的身份码数量是否与产品数量包装一致
            Map<String, Integer> packingNumberByNameMap = productList.stream().collect(Collectors.toMap(Product::getName, Product::getPackingNumber));
            for (Map.Entry<String, List<IdentityCodeExcel>> entry : identityCodeExcelMap.entrySet()) {
                IdentityCodeExcel identityCodeExcel = entry.getValue().get(0);
                if (packingNumberByNameMap.get(identityCodeExcel.getProductName()) != entry.getValue().size()) {
                    throw BusinessException.resultCode(ResultCode.EXCEL_PACKING_NUMBER_NOT_PRODUCT);
                }
            }

            // 判断单品到货数量与导入数量是否一致
            List<ArrivalOrderDetailForm> listByArrivalOrderCode = arrivalOrderDetailService.getListByArrivalOrderCode(this.getArrivalCode());
            Map<String, ArrivalOrderDetailForm> arrivalOrderDetailFormMap = listByArrivalOrderCode.stream().collect(Collectors.toMap(ArrivalOrderDetailForm::getProductName, model -> model));
            Map<String, List<IdentityCodeExcel>> identityExcelByProductName = identityCodeExcels.stream().collect(Collectors.groupingBy(IdentityCodeExcel::getProductName));
            for (Map.Entry<String, List<IdentityCodeExcel>> entry : identityExcelByProductName.entrySet()) {
                if (arrivalOrderDetailFormMap.get(entry.getKey()).getArrivalNumber() != entry.getValue().size()) {
                    throw BusinessException.resultCode(ResultCode.EXCEL_NUMBER_NOT_PRODUCT_NUMBER);
                }
            }

            // 开始组装产品信息
            ArrivalOrderForm arrivalOrderForm = arrivalOrderService.getFormData(this.getArrivalCode());
            productInfoIdentityService.batchInsert(identityCodeExcels.stream().map(model -> {
                ArrivalOrderDetailForm arrivalOrderDetailForm = arrivalOrderDetailFormMap.get(model.getProductName());
                return ProductInfoIdentity.builder()
                        .code(SystemCodeUtils.getCode(SystemCodeEnum.PRODUCT_IDENTITY))
                        .actualStatus(ProductActualStatusEnum.IN_WAREHOUSE.getCode())
                        .backstageStatus(BackstageStatusEnum.IN_WAREHOUSE.getCode())
                        .backstageCode(arrivalOrderForm.getWarehouseCode())
                        .backstageName(arrivalOrderForm.getWarehouseName())
                        .arrivalOrderDetailCode(arrivalOrderDetailForm.getCode())
                        .lostStatus(0)
                        .actualLocationCode(arrivalOrderForm.getWarehouseCode())
                        .actualLocationName(arrivalOrderForm.getWarehouseName())
                        .productCode(arrivalOrderDetailForm.getProductCode())
                        .productName(model.getProductName())
                        .productDate(arrivalOrderDetailForm.getProductDate())
                        .backstageStatus(BackstageStatusEnum.IN_WAREHOUSE.getCode())
                        .identityCode(model.getIdentityCode())
                        .packingCode(model.getPackingCode()).build()
                        ;
            }).toList());
            arrivalOrderService.arrivalScan(arrivalCode, ArrivalScanStatusEnum.COMPLETELY.getCode());
        } finally {
            this.setArrivalCode("");
            identityCodeExcels.clear();
        }
    }
}
